#include "apue.h"
#include <fcntl.h>
#include <sys/time.h>
#include <sys/wait.h>

static void writelockabyte(const char *name, int fd, off_t off) {
    if (writew_lock(fd, off, SEEK_SET, 1) < 0)  
        err_sys("%s: writew_lock error", name);
    printf("%s got the write-lock, byte %lld.\n", name, (long long)off);
}

static void readlockabyte(const char *name, int fd, off_t off) {
    if (readw_lock(fd, off, SEEK_SET, 1) < 0)
        err_sys("%s: readw_lock error", name);
    printf("%s got the read-lock, byte %lld.\n", name, (long long)off);
}

int main(int argc, char *argv[]) {
    int fd, p_wait; 
    pid_t pid;
    struct timeval s, e;

    p_wait= 6;
    gettimeofday(&s, NULL);

    if ((fd= open("templock", O_RDWR|O_CREAT|O_TRUNC, FILE_MODE)) < 0)
        err_sys("open error");
    if (write(fd, "ab", 2) < 0)
        err_sys("write error");
    
    TELL_WAIT();
    if ((pid= fork()) < 0)
        err_sys("fork error");

    if (pid > 0) {
        WAIT_CHILD();
        printf("parent want get write lock(Im wait %d second).\n", p_wait);
        writelockabyte("parent", fd, 1);
        if (waitpid(pid, NULL, 0) < 0)
            err_sys("waitpid error");
        gettimeofday(&e, NULL);
        if ((e.tv_sec - s.tv_sec > p_wait) 
                || (e.tv_sec - s.tv_sec == 6 && e.tv_usec > s.tv_usec)) {
            printf("parent wait timeout\n");
        } else {
            printf("parent had execute power\n");
        }

    } else {
        char buf[100];
        sprintf(buf, "child(%d)", getpid());
        readlockabyte(buf, fd, 1);
        TELL_PARENT(getppid());
        printf("child sleep %d's\n", 4);
        sleep(2);
        
        if ((pid= fork()) < 0)
            err_sys("fork error");
        if (pid > 0) {
            sleep(2);
            printf("child exit\n");
        } else {
            sprintf(buf, "child child(%d)", getpid());
            readlockabyte(buf, fd, 1);
            printf("%s sleep 6 second\n", buf);
            sleep(6);
            printf("%s exit\n", buf);
        }
    }
}
